﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows8Accelerator.Core.Xaml.Controls;
using Windows8Accelerator.Core.Xaml.Storage;
using Windows8Accelerator.Core.Xaml.ViewModels;

namespace Windows8Accelerator.Core.Xaml.Helpers
{
    public class AppHelper : AppHelperBase
    {
        #region Dispatcher
        public static async Task RunOnUIAsync(Action action, CoreDispatcherPriority priority = CoreDispatcherPriority.Low)
        {
            if (Dispatcher.HasThreadAccess)
                action();
            else
                await Dispatcher.RunAsync(priority, ()=>action());
        }

        private static CoreDispatcher _Dispatcher;
        public static CoreDispatcher Dispatcher
        {
            get {
                return _Dispatcher;
            }
        }

        public override void RunOnUIAsync(Action action)
        {
            RunOnUIAsync(action);
        }
        #endregion Dispatcher

        #region Abstract Methods Implementation

        public override async Task NavigateAsync(Type pageType)
        {
            Frame.Navigate(pageType);
        }

        public override async Task NavigateAsync(Type pageType, object parameter)
        {
            Frame.Navigate(pageType, parameter);
        }

        public override void TryUnsnap()
        {
            if (ApplicationView.Value == ApplicationViewState.Snapped)
                ApplicationView.TryUnsnap();
        }

        public override ApplicationViewMode ApplicationViewMode
        {
            get
            {
                switch (ApplicationView.Value)
                {
                    case ApplicationViewState.Filled:
                        return Helpers.ApplicationViewMode.Filled;
                    case ApplicationViewState.FullScreenLandscape:
                    default:
                        return Helpers.ApplicationViewMode.Landscape;
                    case ApplicationViewState.FullScreenPortrait:
                        return Helpers.ApplicationViewMode.Portrait;
                    case ApplicationViewState.Snapped:
                        return Helpers.ApplicationViewMode.Snapped;
                }
            }
        }

        protected override void InternalInitialize()
        {
            Application.Current.Suspending += Current_Suspending;
        }

        public override async Task NavigateBack()
        {
            if (CanNavigateBack)
                Frame.GoBack();
        }

        public override bool CanNavigateBack
        {
            get { return Frame.CanGoBack; }
        }

        #endregion 

        #region Platform Specific Code

        public static Frame Frame
        {
            get
            {
                return Window.Current.Content as Frame;
            }
        }

        public static Page CurrentPage
        {
            get
            {
                if (Frame == null)
                    return null;
                return Frame.Content as Page;
            }
        }

        async void Current_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            await SaveStateAsync();
            deferral.Complete();
        }

        public static async Task OnSearchActivated(SearchActivatedEventArgs args, Type defaultStartPageType)
        {
            await GetInstance().InitializeApp(args, defaultStartPageType, args.QueryText);
        }

        public static async Task OnActivated(IActivatedEventArgs args, Type defaultStartPageType)
        {
            await GetInstance().InitializeApp(args, defaultStartPageType, null);
        }

        public static async Task OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs args, Type defaultStartPageType, Func<SuperSplashPageViewModel, Task> extendedSplashLoadingFunction = null)
        {
            await GetInstance().InitializeApp(args, defaultStartPageType, args.Arguments, extendedSplashLoadingFunction);
        }

        private static AppHelper GetInstance()
        {
            return AppHelperBase.Instance as AppHelper;
        }

        void Frame_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
        {
            base.Frame_Navigated(e.NavigationMode.ToString(), e.Content, e.Parameter);
        }
      
        private async Task InitializeApp(IActivatedEventArgs args, Type defaultStartPageType, object parameter, Func<SuperSplashPageViewModel, Task> extendedSplashLoadingFunction = null)
        {
            _Dispatcher = CoreWindow.GetForCurrentThread().Dispatcher; 

            if (Frame == null)
            {
                Window.Current.Content = new Frame();
                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    await AppHelperBase.Instance.LoadStateAsync();
                }
            }
            Frame.Navigated += Frame_Navigated;

            if (Frame.Content == null)
            {
                if (extendedSplashLoadingFunction != null)
                {
                    var superSplashPage = new SuperSplashPage(new SuperSplashPageViewModel(args.SplashScreen.ImageLocation, parameter, extendedSplashLoadingFunction, defaultStartPageType));
                    await superSplashPage.PreLoadAsync();
                    Frame.Content = superSplashPage;
                }
                else if (!Frame.Navigate(defaultStartPageType, parameter))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            Window.Current.Activate();
        }

        #endregion


        public override async Task ShowErrorMessageAndQuitAsync(string title, string message)
        {
            var messageDialog = new MessageDialog(message, title);
            await messageDialog.ShowAsync();
            Application.Current.Exit();
        }

        public override async Task ShowErrorMessageAndGoBackAsync(string title, string message)
        {
            var messageDialog = new MessageDialog(message, title);
            await messageDialog.ShowAsync();
            await NavigateBack();
        }
    }
}
